home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- windutil.c
-
- This reusable module contains miscellaneous window management
- utility routines.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include "def.h"
- #include "windutil.h"
- #include "drawutil.h"
- #include "memutil.h"
-
-
-
- typedef struct TWindowRecordStorage {
- CWindowRecord storage; /* window record storage */
- Boolean fromFreeList; /* true if storage obtained from free list */
- struct TWindowRecordStorage *next; /* pointer to next available free buffer */
- } TWindowRecordStorage;
-
-
-
- static TWindowRecordStorage *freeWindowRecordStorage = nil; /* pointer to first free buffer */
-
-
-
- /*----------------------------------------------------------------------------
- MyFrontWindow
-
- Get the frontmost window which belongs to the application.
-
- Exit: function result = pointer to window record, or nil if none.
- ----------------------------------------------------------------------------*/
-
- WindowPtr MyFrontWindow (void)
- {
- WindowPeek windPeek;
-
- windPeek = (WindowPeek)FrontWindow();
- while (windPeek != nil && windPeek->windowKind < 0)
- windPeek = windPeek->nextWindow;
- return (WindowPtr)windPeek;
- }
-
-
-
- /*----------------------------------------------------------------------------
- InitializeWindowRecordStorage
-
- Preallocate window record storage buffers in high memory.
-
- Entry: maxWindows = number of buffers to allocate.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr InitializeWindowRecordStorage (short maxWindows)
- {
- short i;
- Handle h;
- TWindowRecordStorage **storage;
- OSErr err = noErr;
-
- for (i = 0; i < maxWindows; i++) {
- err = MyNewHandle(sizeof(TWindowRecordStorage), &h);
- if (err != noErr) return err;
- MyHLockHi(h);
- storage = (TWindowRecordStorage**)h;
- (**storage).next = freeWindowRecordStorage;
- (**storage).fromFreeList = true;
- freeWindowRecordStorage = *storage;
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MyNewWindow
-
- Create a new window. The window is a color window if we have color QD,
- otherwise it's a black and white window.
-
- Entry: rBounds = bounding rectangle in global coordinates.
- title = Pascal format window title string.
- visFlag = true to draw window, false to not draw window.
- wDefProcID = window definition ID.
- behind = -1 if in front, nil if in back, else pointer to window
- behind which this one will be placed.
- goAwayFlag = true if window has close box.
- refCon = application-defined reference.
-
- Exit: function result = error code.
- *wind = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr MyNewWindow (Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID,
- WindowPtr behind, Boolean goAwayFlag, long refCon, WindowPtr *wind)
- {
- TWindowRecordStorage *storage;
- OSErr err = noErr;
-
- storage = freeWindowRecordStorage;
- if (storage == nil) {
- err = MyNewPtr(sizeof(TWindowRecordStorage), &storage);
- if (err != noErr) return err;
- storage->fromFreeList = false;
- } else {
- freeWindowRecordStorage = storage->next;
- }
- if (HasColorQD()) {
- *wind = NewCWindow((CWindowRecord*)storage, rBounds, title, visFlag,
- wDefProcID, behind, goAwayFlag, refCon);
- } else {
- *wind = NewWindow((CWindowRecord*)storage, rBounds, title, visFlag,
- wDefProcID, behind, goAwayFlag, refCon);
- }
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MyDisposeWindow
-
- Dispose a window.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void MyDisposeWindow (WindowPtr wind)
- {
- TWindowRecordStorage *storage;
-
- if (wind == nil) return;
- storage = (TWindowRecordStorage*)wind;
- CloseWindow(wind);
- if (storage->fromFreeList) {
- storage->next = freeWindowRecordStorage;
- freeWindowRecordStorage = storage;
- } else {
- MyDisposePtr(storage);
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- IsDAWindow
-
- Check to see if a window belongs to a desk accessory.
-
- Entry: wind = pointer to window.
-
- Exit: function result = true if window belongs to a DA.
- ----------------------------------------------------------------------------*/
-
- Boolean IsDAWindow (WindowPtr wind)
- {
- if (wind == nil) {
- return false;
- } else {
- return ((WindowPeek)wind)->windowKind < 0;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- GetWindRegionRects
-
- Return the bounding rects of a window's content and structure regions.
-
- Entry: wind = pointer to window.
-
- Exit: contRect = content region bounding rect.
- strucRect = structure region bounding rect.
-
- Adapted from Dean Yu's code in Develop #17.
- ----------------------------------------------------------------------------*/
-
- void GetWindRegionRects (WindowPtr wind, Rect *contRect, Rect *strucRect)
- {
- GrafPtr port;
- RgnHandle contRgn, strucRgn;
- Rect portRect, userState, stdState;
- WStateData **wState;
-
- GetPort(&port);
- SetPort(wind);
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- userState = (**wState).userState;
- stdState = (**wState).stdState;
- if (((WindowPeek)wind)->visible) {
- contRgn = ((WindowPeek)wind)->contRgn;
- strucRgn = ((WindowPeek)wind)->strucRgn;
- *contRect = (**contRgn).rgnBBox;
- *strucRect = (**strucRgn).rgnBBox;
- } else {
- portRect = wind->portRect;
- LocalToGlobalRect(&portRect);
- MoveWindow(wind, -0x4000, -0x4000, false);
- ShowHide(wind, true);
- contRgn = ((WindowPeek)wind)->contRgn;
- strucRgn = ((WindowPeek)wind)->strucRgn;
- *contRect = (**contRgn).rgnBBox;
- *strucRect = (**strucRgn).rgnBBox;
- OffsetRect(contRect, portRect.left + 0x4000, portRect.top + 0x4000);
- OffsetRect(strucRect, portRect.left + 0x4000, portRect.top + 0x4000);
- ShowHide(wind, false);
- MoveWindow(wind, portRect.left, portRect.top, false);
- }
- (**wState).userState = userState;
- (**wState).stdState = stdState;
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- GetDominantScreen
-
- Return the screen with the maximum intersection with a window.
-
- Entry: wind = pointer to window.
-
- Exit: screenRect = dominant screen's rectangle.
- mainScreen = true if main screen (with menu bar).
- onOneScreen = true if window completely contained on one screen.
-
- Adapted from Dean Yu's code in Develop #17.
- ----------------------------------------------------------------------------*/
-
- typedef struct TGetDominantScreenUserData {
- GDHandle mainDevice;
- GDHandle maxDevice;
- long maxArea;
- Rect windBounds;
- } TGetDominantScreenUserData;
-
- static pascal void GetDominantScreenOneDevice (short depth, short deviceFlags,
- GDHandle targetDevice, long userData)
- {
- TGetDominantScreenUserData *ud;
- Rect r, deviceRect;
- long area;
-
- ud = (TGetDominantScreenUserData*)userData;
- deviceRect = (**targetDevice).gdRect;
- if (targetDevice == ud->mainDevice) deviceRect.top += GetMBarHeight();
- SectRect(&ud->windBounds, &deviceRect, &r);
- OffsetRect(&r, -r.left, -r.top);
- area = (long)r.right * (long)r.bottom;
- if (area > ud->maxArea) {
- ud->maxArea = area;
- ud->maxDevice = targetDevice;
- }
- }
-
- void GetDominantScreen (WindowPtr wind, Rect *screenRect, Boolean *mainScreen,
- Boolean *onOneScreen)
- {
- GrafPtr port;
- RgnHandle rgn;
- Rect contRect, strucRect, deviceLoopRect;
- TGetDominantScreenUserData ud;
- static DeviceLoopDrawingUPP upp = nil;
-
- if (upp == nil) upp = NewDeviceLoopDrawingProc(GetDominantScreenOneDevice);
-
- if (wind == nil) {
- if (!HasColorQD()) {
- *screenRect = qd.screenBits.bounds;
- } else {
- ud.mainDevice = GetMainDevice();
- *screenRect = (**ud.mainDevice).gdRect;
- }
- *mainScreen = true;
- *onOneScreen = true;
- return;
- }
-
- GetPort(&port);
- SetPort(wind);
- GetWindRegionRects(wind, &contRect, &strucRect);
- if (!HasColorQD()) {
- *screenRect = qd.screenBits.bounds;
- *mainScreen = true;
- goto exit;
- }
- ud.mainDevice = GetMainDevice();
- ud.maxDevice = ud.mainDevice;
- ud.maxArea = 0;
- rgn = NewRgn();
- SectRgn(GetGrayRgn(), ((WindowPeek)wind)->contRgn, rgn);
- if (EmptyRgn(rgn)) {
- ud.windBounds = strucRect;
- } else {
- ud.windBounds = contRect;
- }
- deviceLoopRect = ud.windBounds;
- GlobalToLocalRect(&deviceLoopRect);
- RectRgn(rgn, &deviceLoopRect);
- DeviceLoop(rgn, upp, (long)&ud, singleDevices);
- DisposeRgn(rgn);
- *screenRect = (**ud.maxDevice).gdRect;
- *mainScreen = ud.maxDevice == ud.mainDevice;
-
- exit:
-
- if (*mainScreen) strucRect.top -= GetMBarHeight();
- *onOneScreen = strucRect.top >= screenRect->top &&
- strucRect.bottom <= screenRect->bottom &&
- strucRect.left >= screenRect->left &&
- strucRect.right <= screenRect->right;
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- WindOnScreen
-
- Check to see if a window is completely within a single screen.
-
- Entry: wind = pointer to window.
-
- Exit: function result = true if window is completely within a
- single screen.
- ----------------------------------------------------------------------------*/
-
- Boolean WindOnScreen (WindowPtr wind)
- {
- Rect screenRect;
- Boolean mainScreen, onOneScreen;
-
- GetDominantScreen(wind, &screenRect, &mainScreen, &onOneScreen);
- return onOneScreen;
- }
-
-
-
- /*----------------------------------------------------------------------------
- StaggerWindow
-
- Stagger a new window.
-
- Entry: wind = pointer to window.
- width = window width.
- height = window height.
- offsetFrom = pointer to window from which this window should be
- offset, or nil if none.
- dontCoverFinderIcons = true to avoid covering up Finder icons.
- ----------------------------------------------------------------------------*/
-
- void StaggerWindow (WindowPtr wind, short width, short height, WindowPtr offsetFrom,
- Boolean dontCoverFinderIcons)
- {
- Rect screenRect, r, contRect, strucRect;
- WStateData **wState;
- GrafPtr port;
- Boolean mainScreen, onOneScreen, topLeft = false;
-
- GetPort(&port);
- SetPort(wind);
- SizeWindow(wind, width, height, false);
- GetWindRegionRects(wind, &contRect, &strucRect);
- GetDominantScreen(offsetFrom, &screenRect, &mainScreen, &onOneScreen);
- if (mainScreen) {
- screenRect.top += GetMBarHeight();
- }
- if (offsetFrom == nil) {
- topLeft = true;
- } else {
- r = offsetFrom->portRect;
- SetPort(offsetFrom);
- LocalToGlobalRect(&r);
- SetPort(wind);
- MoveWindow(wind, r.left + 20, r.top + 20, false);
- if (!WindOnScreen(wind)) {
- topLeft = true;
- } else if (dontCoverFinderIcons && mainScreen &&
- screenRect.right - screenRect.left > 576)
- {
- r = wind->portRect;
- LocalToGlobalRect(&r);
- if (r.right + 64 > screenRect.right) topLeft = true;
- }
- }
- if (topLeft) {
- MoveWindow(wind,
- screenRect.left + contRect.left - strucRect.left + 4,
- screenRect.top + contRect.top - strucRect.top + 4,
- false);
- }
-
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- r = wind->portRect;
- LocalToGlobalRect(&r);
- (**wState).userState = r;
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- CalculateZoomRect
-
- Calculate the zoomed rectangle for a window.
-
- Entry: wind = pointer to window.
- width = desired width of zoomed window if infinite screen.
- height = desired height of zoomed window if infinite screen.
- dontCoverFinderIcons = true to avoid covering up Finder icons.
-
- Exit: *zoomRect = zoomed rectangle for the window.
- ----------------------------------------------------------------------------*/
-
- void CalculateZoomRect (WindowPtr wind, short width, short height,
- Rect *zoomRect, Boolean dontCoverFinderIcons)
- {
- Rect windRect, screenRect, contRect, strucRect;
- short leftDiff, topDiff, rightDiff, bottomDiff;
- short screenWidth, screenHeight;
- Boolean mainScreen, onOneScreen;
-
- GetDominantScreen(wind, &screenRect, &mainScreen, &onOneScreen);
- GetWindRegionRects(wind, &contRect, &strucRect);
- leftDiff = contRect.left - strucRect.left;
- topDiff = contRect.top - strucRect.top;
- rightDiff = strucRect.right - contRect.right;
- bottomDiff = strucRect.bottom - contRect.bottom;
-
- if (mainScreen) {
- screenRect.top += GetMBarHeight();
- if (dontCoverFinderIcons && screenRect.right - screenRect.left > 576)
- screenRect.right -= 64;
- }
- InsetRect(&screenRect, 4, 4);
-
- width += leftDiff + rightDiff;
- if (height < 0x7000) height += topDiff + bottomDiff;
- screenWidth = screenRect.right - screenRect.left;
- screenHeight = screenRect.bottom - screenRect.top;
- if (width > screenWidth) width = screenWidth;
- if (height > screenHeight) height = screenHeight;
-
- windRect = wind->portRect;
- LocalToGlobalRect(&windRect);
- windRect.left -= leftDiff;
- windRect.top -= topDiff;
- windRect.right = windRect.left + width;
- windRect.bottom = windRect.top + height;
-
- if (windRect.left < screenRect.left)
- OffsetRect(&windRect, screenRect.left - windRect.left, 0);
- if (windRect.right > screenRect.right)
- OffsetRect(&windRect, screenRect.right - windRect.right, 0);
- if (windRect.top < screenRect.top)
- OffsetRect(&windRect, 0, screenRect.top - windRect.top);
- if (windRect.bottom > screenRect.bottom)
- OffsetRect(&windRect, 0, screenRect.bottom - windRect.bottom);
-
- windRect.left += leftDiff;
- windRect.top += topDiff;
- windRect.right -= rightDiff;
- windRect.bottom -= bottomDiff;
-
- *zoomRect = windRect;
- }
-
-
-
- /*----------------------------------------------------------------------------
- WindRectEqualRect
-
- Check to see if a window's rectangle equals a rectangle.
-
- Entry: wind = pointer to window.
- r = pointer to rectangle in global coords.
-
- Exit: function result = true if window's rectangle is equal to
- the specified global rectange.
- ----------------------------------------------------------------------------*/
-
- Boolean WindRectEqualRect (WindowPtr wind, Rect *r)
- {
- GrafPtr port;
- Rect windRect;
-
- GetPort(&port);
- windRect = wind->portRect;
- SetPort(wind);
- LocalToGlobalRect(&windRect);
- SetPort(port);
- return EqualRect(&windRect, r);
- }
-
-
-
- /*----------------------------------------------------------------------------
- SetWindowNeedsZooming
-
- Set a window standard state to (0,0,0,0) to force a zoom out on the next
- zoom.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void SetWindowNeedsZooming (WindowPtr wind)
- {
- WStateData **wState;
-
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- SetRect(&(**wState).stdState, 0, 0, 0, 0);
- }
-